#include "../DWMRICore/Scalar.h"

char *src_pathname = NULL;
char *dst_pathname = NULL;

int mode = 0;		/* 0 for erode, 1 for dilate */

void PrintUsage()
{
	printf("Usage: Erode [-d] -src <src_file> -dst <dst_file>\n");
}

int ParseArguments(const int argc, char *argv[])
{
	for (int i = 1; i < argc; ++i) {
		if (strcmp(argv[i], "-src") == 0) {
			src_pathname = argv[++i];
		} else if (strcmp(argv[i], "-dst") == 0) {
			dst_pathname = argv[++i];
		} else if (strcmp(argv[i], "-d") == 0) {
			mode = 1;
		} else {
			return -1;
		}
	}

	if (src_pathname == NULL || dst_pathname == NULL)
		return -2;

	return 0;
}

void Erode(CScalar *pSRC)
{
	int w = pSRC->GetWidth();
	int h = pSRC->GetHeight();
	int d = pSRC->GetDepth();

	for (int z = 0; z < d; ++z) {
		for (int y = 0; y < h; ++y) {
			for (int x = 0; x < w; ++x) {
				if (pSRC->GetScalarFast(x, y, z) < 0.5f) {
					int min_x = (x - 1) < 0 ? 0 : (x - 1);
					int min_y = (y - 1) < 0 ? 0 : (y - 1);
					int min_z = (z - 1) < 0 ? 0 : (z - 1);
					int max_x = (x + 1) < w ? x + 1 : w - 1;
					int max_y = (y + 1) < h ? y + 1 : h - 1;
					int max_z = (z + 1) < d ? z + 1 : d - 1;

					for (int cz = min_z; cz <= max_z; ++cz) {
						for (int cy = min_y; cy <= max_y; ++cy) {
							for (int cx = min_x; cx <= max_x; ++cx) {
								if (pSRC->GetScalarFast(cx, cy, cz) > 0.5f) {
									pSRC->SetScalar(cx, cy, cz, 2.0f);
								}
							}
						}
					}
				}
			}
		}
	}

	for (int z = 0; z < d; ++z) {
		for (int y = 0; y < h; ++y) {
			for (int x = 0; x < w; ++x) {
				if (pSRC->GetScalarFast(x, y, z) > 1.5f) {
					pSRC->SetScalar(x, y, z, 0.0f);
				}
			}
		}
	}
}

void Dilate(CScalar *pSRC)
{
	int w = pSRC->GetWidth();
	int h = pSRC->GetHeight();
	int d = pSRC->GetDepth();

	for (int z = 0; z < d; ++z) {
		for (int y = 0; y < h; ++y) {
			for (int x = 0; x < w; ++x) {
				if (pSRC->GetScalarFast(x, y, z) > 0.5f) {
					int min_x = (x - 1) < 0 ? 0 : (x - 1);
					int min_y = (y - 1) < 0 ? 0 : (y - 1);
					int min_z = (z - 1) < 0 ? 0 : (z - 1);
					int max_x = (x + 1) < w ? x + 1 : w - 1;
					int max_y = (y + 1) < h ? y + 1 : h - 1;
					int max_z = (z + 1) < d ? z + 1 : d - 1;

					for (int cz = min_z; cz <= max_z; ++cz) {
						for (int cy = min_y; cy <= max_y; ++cy) {
							for (int cx = min_x; cx <= max_x; ++cx) {
								if (pSRC->GetScalarFast(cx, cy, cz) < 0.5f) {
									pSRC->SetScalar(cx, cy, cz, -1.0f);
								}
							}
						}
					}
				}
			}
		}
	}

	for (int z = 0; z < d; ++z) {
		for (int y = 0; y < h; ++y) {
			for (int x = 0; x < w; ++x) {
				if (pSRC->GetScalarFast(x, y, z) < -0.5f) {
					pSRC->SetScalar(x, y, z, 1.0f);
				}
			}
		}
	}
}

int main(int argc, char *argv[])
{
	if (ParseArguments(argc, argv) != 0) {
		PrintUsage();
		return 0;
	}

	CScalar *pSRC = new CScalar();
	pSRC->OpenScalarFile(src_pathname);

	uint w = pSRC->GetWidth();
	uint h = pSRC->GetHeight();
	uint d = pSRC->GetDepth();

	if (mode == 0) {
		// erode
		Erode(pSRC);
	} else {
		//dilate
		Dilate(pSRC);
	}

	pSRC->SaveScalarFile(dst_pathname);

	SafeDelete(pSRC);

	return 0;
}